package com.kly.user.serviceImpl;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.api.client.util.Lists;
import com.google.common.collect.Maps;
import com.google.common.eventbus.AsyncEventBus;
import com.kly.enums.ParameterTypeEnum;
import com.kly.service.UserVasPurchasesService;
import com.kly.user.chatterService.ChatService;
import com.kly.user.config.NacosValueConfig;
import com.kly.user.constant.ConstantType;
import com.kly.user.constant.RedisKey;
import com.kly.user.db.dao.*;
import com.kly.user.db.entity.*;
import com.kly.user.dto.*;
import com.kly.user.dto.chatter.request.ConversationReq;
import com.kly.user.enums.*;
import com.kly.user.eventbus.ActionEnum;
import com.kly.user.eventbus.Event;
import com.kly.user.mapper.InterestMapper;
import com.kly.user.msgClient.MsgAPI;
import com.kly.user.service.AdjustService;
import com.kly.user.service.AppsflyerService;
import com.kly.user.service.OtherService;
import com.kly.user.service.UserMsgService;
import com.kly.user.task.service.CommonUtilityService;
import com.kly.user.utils.FeishuPushUtil;
import com.kly.user.utils.ImagePrefixUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service("otherService")
public class OtherServiceImpl implements OtherService {
    private static Log logger = LogFactory.getLog(OtherService.class);

    @Resource
    InterestDao interestDao;
    @Resource
    InterestMapper interestMapper;
    @Resource
    TMessageDao messageDao;
    @Resource
    TMessageReadDao messageReadDao;
    @Resource
    AsyncEventBus asyncEventBus;
    @Resource
    UserConversationDao conversationDao;
    @Resource
    UserMsgDao userMsgDao;
    @Resource
    UserConversationGroupDao userConversationGroupDao;
    @Resource
    UserChatterMappingDao userChatterMappingDao;
    @Resource
    UserImageVideoSendLogsDao userImageVideoSendLogsDao;
    @Resource
    CommonUtilityService commonUtilityService;
    @Resource
    AppsflyerService appsflyerService;
    @Resource
    UserCommonLogDao commonLogDao;
    @Resource
    UserVasPurchasesService userVasPurchasesService;
    @Resource
    ChatService chatService;
    @Resource
    UserMsgUnreadNumDao userMsgUnreadNumDao;
    @Resource
    ChatterOptLogDao chatterOptLogDao;
    @Resource
    private UserMessageReportDao userMessageReportDao;
    @NacosValue(value = "${push.msessage.switch:false}", autoRefreshed = true)
    private Boolean pushEnable;
    @NacosValue(value = "${addmessage.pushddata.enable}", autoRefreshed = true)
    private boolean pushDataSwitch;
    @Resource
    RedisClient redisClient;
    @Resource
    UserMsgListDao userMsgListDao;
    @Resource
    MessageCmStausDao messageCmStausDao;
    @Resource
    PageContentConfigDao pageContentConfigDao;
    @Resource
    SystemDictDao systemDictDao;
    @Resource
    UserNameDictDao userNameDictDao;
    @Resource
    AdjustService adjustService;
    @Resource
    UserMsgService userMsgService;

    @Resource
    private SystemQaDao systemQaDao;
    @Resource
    private FeishuPushUtil feishuPushUtil;
    @Resource
    private NacosValueConfig nacosValueConfig;

    @Override
    public Response<List<InterestDto>> getInterests() {
        List<InterestEntity> interestEntities = interestDao.selectByParams(new HashMap<>());
        List<InterestDto> interestDtoList = new ArrayList<>();
        if (interestEntities != null && !interestEntities.isEmpty()) {
            for (InterestEntity interest : interestEntities) {
                InterestDto interestDto = interestMapper.toDto(interest);
                interestDtoList.add(interestDto);
            }
        }
        return Response.ok(interestDtoList);
    }

    @Override
    public Response addMessage(AddMessageReq req) {
        logger.info("addMessage:{}", JSONObject.toJSONString(req));
        // 多端同步消息不记录
        if ("RC:SRSMsg".equalsIgnoreCase(req.getObjectName())) {
            return Response.ok();
        }

        // 已经发送过，不需要再次发送flashchat消息
        final String msgId = redisClient.getString(RedisKey.MSG_SEND, req.getFromUserId(), req.getToUserId());
        if (StringUtils.isNotBlank(msgId) && msgId.equals(req.getMsgUID())) {
            return Response.ok();
        }

        // 本条消息是否来自meboo标志
        boolean isFromMeboo = isFromMeboo(req);
        // 从消息报文中获取chatterUserCode
        final String chatterUserCodeFromContent = getChatterUserCode(req, pushEnable);
        // 消息存储
        final UserMsgEntity msgEntity = storeMsg(req, chatterUserCodeFromContent);

        // 保存一条对方用户的会话（非当前用户）
        addConversation(req, isFromMeboo, chatterUserCodeFromContent, msgEntity);

        // 推送通知消息到meboo或mechat
        pushNotification(req, pushEnable);

        pushWorkerNotice(req);

        // 推送有效会话及深度会话到appsflyer
//        pushDataToAdjust(req);

        return Response.ok();
    }

    private void pushWorkerNotice(AddMessageReq req) {
        logger.info("pushWorkerNotice starts. {}, {}", req.getFromUserId(), req.getToUserId());
        if (!nacosValueConfig.feishuPushSwitch()) {
            logger.info("==FeishuTaskBase 发送给飞书的报警开关未打开  ==");
            return;
        }
        if (!nacosValueConfig.ppWlmIssueFixUserCode().contains(req.getToUserId())) {
            logger.info(">>>>>>>推送飞书消息失败，接受人不在配置素人用户中 {}", req.getToUserId());
            return;
        }

        List<String> userCodes = Arrays.asList(req.getFromUserId(), req.getToUserId());
        Map<String, Object> params = Maps.newConcurrentMap();
        params.put("list", userCodes);
        final List<UserEntity> userList = userDao.selectUsers(params);
        if (CollectionUtils.isEmpty(userList) || userList.size() < userCodes.size()) {
            logger.info(">>>>>>>推送飞书消息失败，查询用户信息失败 {}", userCodes);
            return;
        }

        String text;
        if (userList.get(0).getUserCode().equals(req.getFromUserId())) {
            text = "普通用户" + userList.get(0).getNickName() + "【" + req.getFromUserId() + "】给配置素人用户" + userList.get(1).getNickName() + "【" + req.getToUserId() + "】发送了消息，请及时回复！";
        } else {
            text = "普通用户" + userList.get(1).getNickName() + "【" + req.getFromUserId() + "】给配置素人用户" + userList.get(0).getNickName() + "【" + req.getToUserId() + "】发送了消息，请及时回复！";
        }

        feishuPushUtil.sendTextMessage(text);
        logger.info("pushWorkerNotice ends. {}, {}", req.getFromUserId(), req.getToUserId());
    }

    private void addConversation(AddMessageReq req, boolean isFromMeboo, String chatterUserCodeFromContent, UserMsgEntity msgEntity) {
        final ConversationReq conversationReq = ConversationReq.builder().fromUserCode(req.getFromUserId()).toUserCode(req.getToUserId()).latestMsg(req.getContent()).chatterUserCode(chatterUserCodeFromContent).sessionId(msgEntity.getSessionId()).type(1).latestTime(new Date()).conversationType(1).build();
        if (isFromMeboo) {
            conversationReq.setSource(AppEnum.MEBOO.getAppCode());
        } else {
            conversationReq.setSource(AppEnum.MECHAT.getAppCode());
        }
        chatService.storageConversation(conversationReq);
    }

    private boolean isFromMeboo(AddMessageReq req) {
        final UserEntity userEntity = userDao.selectByUserCode(req.getFromUserId());
        return UserType.NORMAL_USER.getType() == userEntity.getUserType() ;
    }

    @Resource
    MsgAPI msgAPI;
    private void pushNotification(AddMessageReq req, Boolean pushEnable) {
        try {
            final String chatterUserCodeFromContent = getChatterUserCodeFromContent(req, pushEnable);
            if (!pushEnable) {
                return;
            }
            if (StringUtils.isNotBlank(chatterUserCodeFromContent)) {
                Event event = buildEvent(req, AppEnum.MEBOO);
                if (event != null) {
                    JSONObject jsonObject = JSONObject.parseObject(event.getContent());
                    if (!jsonObject.getBoolean("isNotification")) {
                        asyncEventBus.post(event);
                    }
                }
            } else {

                final List<UserChatterMappingEntity> userChatterMappingEntities = userChatterMappingDao.queryByModelUserCode(req.getToUserId());
                logger.info("onlineChatters:{}", JSONObject.toJSONString(userChatterMappingEntities));
                if (CollectionUtils.isEmpty(userChatterMappingEntities)) {
                    return;
                }
                String chatterUserCode = userChatterMappingEntities.get(0).getChatterUserCode();
                Map<String, Object> params = new HashMap<>();
                params.put("type", ParameterTypeEnum.MESSAGE_FEEDBACK.getId());
                params.put("bizCode", "M20001");
                params.put("userCode", req.getFromUserId());
                params.put("modelUserCode", req.getToUserId());
                Event event = Event.builder().eventActionEnum(ActionEnum.PUSH_MSG).app(AppEnum.MECHAT).fromUserCode(req.getFromUserId()).toUserCode(chatterUserCode).content(JSONObject.toJSONString(params)).build();
                asyncEventBus.post(event);

            }
        } catch (Exception e) {
            logger.error("AddPushMessageFailed:{}", JSONObject.toJSONString(req), e);
        }
    }

    /**
     * 推送有效会话及深度会话到appsflyer
     */
    private void pushDataToAppsFlyer(AddMessageReq req) {
        try {
            if (pushDataSwitch) {
                final UserEntity userEntity = userDao.selectByUserCode(req.getFromUserId());
                if (UserType.NORMAL_USER.getType() == userEntity.getUserType()) {
                    final HashMap<String, Object> params = Maps.newHashMap();
                    params.put("fromUserCode", req.getFromUserId());
                    params.put("toUserCode", req.getToUserId());
                    final Integer msgNum = userMsgDao.queryTotal(params);
                    params.put("msgNum", msgNum);
                    // 深度会话：单段关系中男用户累计发送消息数>=30条，即算一个深度会话
                    if (GenderEnum.MAN.getType() == userEntity.getGender() && msgNum == 30) {
                        params.put("userCode", req.getFromUserId());
                        appsflyerService.asyncTraceEvent(AppsFlyerEventDefType.Deep_Chat, params);
                    } else if (msgNum == 4) {
                        params.put("userCode", req.getFromUserId());
                        appsflyerService.asyncTraceEvent(AppsFlyerEventDefType.Active_Chat, params);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("AddDataToAppsFlyerFailed:{}", JSONObject.toJSONString(req), e);
        }
    }

    /**
     * 推送有效会话及深度会话到adjust
     */
    private void pushDataToAdjust(AddMessageReq req) {
        try {
            if (pushDataSwitch) {
                final UserEntity userEntity = userDao.selectByUserCode(req.getFromUserId());
                if (UserType.NORMAL_USER.getType() == userEntity.getUserType()) {
                    final HashMap<String, Object> params = Maps.newHashMap();
                    params.put("fromUserCode", req.getFromUserId());
                    params.put("toUserCode", req.getToUserId());
                    final Integer msgNum = userMsgDao.queryTotal(params);
                    params.put("msgNum", msgNum);

                    // 深度会话：单段关系中男用户累计发送消息数>=30条，即算一个深度会话
                    if (GenderEnum.MAN.getType() == userEntity.getGender() && msgNum == 30) {
                        params.put("userCode", req.getFromUserId());
                        adjustService.asyncTraceEvent(AdjustEventDefType.Break_ice_Chat, params);
                    } else if (msgNum == 4) {
                        params.put("userCode", req.getFromUserId());
                        adjustService.asyncTraceEvent(AdjustEventDefType.Active_Chat, params);
                    } else if (msgNum == 1) {
                        params.put("userCode", req.getFromUserId());
                        adjustService.asyncTraceEvent(AdjustEventDefType.Active_Chat, params);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("AddDataToAppsFlyerFailed:{}", JSONObject.toJSONString(req), e);
        }
    }

    /**
     * 生成sessionID
     */
    private String buildSessionId(AddMessageReq req) {
        String sessionId = null;
        // 如果消息为model发起的，需要通知meboo 用户
        if (StringUtils.isNotBlank(req.getContent()) && req.getContent().contains("chatterCode")) {
            sessionId = req.getFromUserId() + req.getToUserId();
        } else {
            sessionId = req.getToUserId() + req.getFromUserId();
        }
        return SecureUtil.md5(sessionId);
    }


    /**
     * 消息回复需要的报文
     * type 1 回复消息  2普通照片  3私密照片  4普通视频  5私密视频 6wlm喜欢
     * isNotification true 通知栏消息  false应用内消息
     * targetId 目标的userCode
     * imageUrl 对方发送的图片或者视频链接
     */
    @Resource
    UserDao userDao;


    private Event buildEvent(AddMessageReq req, AppEnum appEnum) {
        logger.info("buildEventStart, AppEnum:{} , buildEvent: {}", appEnum, JSONObject.toJSONString(req));
        Map<String, UserEntity> userEntityMap = commonUtilityService.getUserList(req.getFromUserId(), req.getToUserId());
        if (userEntityMap == null) {
            logger.info("MsgAPI.postMatchedRequest userCode is deleted:{}", JSONObject.toJSONString(req));
            return null;
        }
        UserEntity userInfo = userEntityMap.get(req.getFromUserId());
        UserEntity toUserInfo = userEntityMap.get(req.getToUserId());

        Map<String, Object> params = new HashMap<>();
        params.put("targetId", req.getFromUserId());
        params.put("notificationImage", ImagePrefixUtils.getFullImageUrl(userInfo.getAvatarUrl()));
        params.put("type", ParameterTypeEnum.MESSAGE_FEEDBACK.getId());
        params.put("isNotification", toUserInfo.getOnline() != OnlineStatus.ONLINE_STATUS.getType());

        String content = req.getContent();
        if (StringUtils.isNotBlank(content)) {
            JSONObject contentJson = JSONObject.parseObject(content);
            JSONObject fromUserInfo = contentJson.getJSONObject("user");

            if (Objects.equals(appEnum.getAppCode(), AppEnum.MECHAT.getAppCode())) {
                params.put("title", toUserInfo.getNickName() + " got new message");
                String bodyPrefix = fromUserInfo.getString("name") + " ";
                String bodyMessage;
                if (Objects.equals("RC:TxtMsg", req.getObjectName())) {
                    bodyMessage = contentJson.getString("content");
                } else if (Objects.equals("RC:ImgMsg", req.getObjectName())) {
                    bodyMessage = "photo message";
                } else if (Objects.equals("RC:SightMsg", req.getObjectName())) {
                    bodyMessage = "video message";
                } else {
                    bodyMessage = "other message";
                }
                params.put("body", bodyPrefix + bodyMessage);
            } else {
                if (fromUserInfo != null) {
                    params.put("title", fromUserInfo.getString("name"));
                }
                if (Objects.equals("RC:TxtMsg", req.getObjectName())) {
                    params.put("body", contentJson.getString("content"));
                } else if (Objects.equals("RC:ImgMsg", req.getObjectName()) || Objects.equals("RC:SightMsg", req.getObjectName())) {
                    handleMediaMessage(params, contentJson);
                    String imageUrl = contentJson.getString("content");
                    params.put("imageUrl", imageUrl);
                }
            }

        }

        Event event = Event.builder().eventActionEnum(ActionEnum.PUSH_MSG).app(appEnum).fromUserCode(req.getFromUserId())
                .toUserCode(req.getToUserId()).content(JSONObject.toJSONString(params)).build();
        logger.info("buildEventEnd, Event:{}", JSONObject.toJSONString(event));
        return event;
    }

    private void handleMediaMessage(Map<String, Object> params, JSONObject contentJson) {
        String extra = contentJson.getString("extra");
        if (StringUtils.isNotBlank(extra)) {
            extra = extra.replaceAll("=", ":");
            JSONObject extraJson = JSONObject.parseObject(extra);

            int albumType = extraJson.getIntValue("albumType");
            int imageOrVideoFlag = extraJson.getIntValue("type");

            handleAlbum(params, albumType, imageOrVideoFlag);
        }
    }

    private void handleAlbum(Map<String, Object> params, int albumType, int imageOrVideoFlag) {
        boolean isPrivate = AlbumsType.PRIVATE_ALBUMS.getType() == albumType;
        boolean isImage = ImageType.IMAGE.getType() == imageOrVideoFlag;

        String body;
        ParameterTypeEnum type;

        if (isImage) {
            body = isPrivate ? "Sent you a private photo" : "Sent you a photo";
            type = isPrivate ? ParameterTypeEnum.PRIVATE_IMAGE : ParameterTypeEnum.NORMAL_IMAGE;
        } else {
            body = isPrivate ? "Sent you a private video" : "Sent you a video";
            type = isPrivate ? ParameterTypeEnum.PRIVATE_VIDEO : ParameterTypeEnum.NORMAL_VIDEO;
        }

        params.put("type", type.getId());
        params.put("body", body);
    }


    private UserEntity queryUserInfo(AddMessageReq req) {
        UserEntity user = userDao.selectByUserCode(req.getToUserId());
        if (user == null) {
            user = new UserEntity();
            user.setOnline(2);
            return user;
        }
        return user;
    }

    /**
     * pushEnable允许推送消息时，则不需要存储照片发送日志
     */
    @Nullable
    private String getChatterUserCode(AddMessageReq req, boolean pushEnable) {
        String chatterUserCode = req.getGroupUserIds();
        if (StringUtils.isBlank(chatterUserCode)) {
            chatterUserCode = getChatterUserCodeFromContent(req, !pushEnable);
        }
        return chatterUserCode;
    }

    private String getChatterUserCodeFromContent(AddMessageReq req, boolean flag) {
        final String content = req.getContent();
        if (content.startsWith("{") && content.endsWith("}")) {
            JSONObject contentJson = null;
            try {
                contentJson = JSONObject.parseObject(content);
            } catch (Exception e) {
                contentJson = new JSONObject();
                logger.error("ParseMessageRequestError:{}", content, e);
            }
            final String extra = contentJson.getString("extra");
            if (StringUtils.isNotBlank(extra) && extra.contains("chatterCode")) {

                JSONObject extraJson = null;
                try {
                    extraJson = JSONObject.parseObject(extra);
                    if (flag) {
                        //当判断为chatter发送的消息时插入chat发送消息记录表
                        if (extraJson.containsKey("albumType")) {
                            UserImageVideoSendLogsEntity userImageVideoSendLogs = new UserImageVideoSendLogsEntity();
                            userImageVideoSendLogs.setModelUserCode(req.getFromUserId());
                            userImageVideoSendLogs.setUserCode(req.getToUserId());
                            userImageVideoSendLogs.setChatterUserCode(extraJson.getString("chatterCode"));
                            userImageVideoSendLogs.setAlbumType(Integer.valueOf(extraJson.getString("albumType")));
                            userImageVideoSendLogs.setImageCode(extraJson.getString("imageCode"));
                            userImageVideoSendLogs.setImageUrl(contentJson.getString("content"));
                            userImageVideoSendLogs.setImageType(Integer.valueOf(extraJson.getString("type")));
                            userImageVideoSendLogsDao.insert(userImageVideoSendLogs);
                        }

                    }
                } catch (Exception e) {
                    extraJson = new JSONObject();
                    logger.error("ParseMessageExtraError:{}", extra, e);
                }
                return extraJson.getString("chatterCode");
            }
        }
        return null;
    }

    /**
     * 消息存储, chatterUserCode非空，为mechat发出的消息，其它为meboo发出的消息
     */
    private UserMsgEntity storeMsg(AddMessageReq req, String chatterUserCode) {

        // 消息原始数据存储
        UserMsgEntity userMsgEntity = storeMsgContent(req, chatterUserCode);

        // message 消息存储
        storeMsgList(req, chatterUserCode, userMsgEntity.getSessionId());

        redisClient.set(RedisKey.MSG_SEND, req.getMsgUID(), 20, req.getFromUserId(), req.getToUserId());
        return userMsgEntity;
    }

    @NotNull
    private UserMsgEntity storeMsgContent(AddMessageReq req, String chatterUserCode) {
        UserMsgEntity userMsgEntity = new UserMsgEntity();
        userMsgEntity.setFromUserCode(req.getFromUserId());
        userMsgEntity.setSource(req.getSource());
        userMsgEntity.setToUserCode(req.getToUserId());
        userMsgEntity.setContent(req.getContent());
        userMsgEntity.setMsgType(req.getObjectName());
        userMsgEntity.setMsgId(req.getMsgUID());
        userMsgEntity.setChatterUserCode(chatterUserCode);
        if (StringUtils.isBlank(chatterUserCode)) {
            userMsgEntity.setSessionId(SecureUtil.md5(userMsgEntity.getFromUserCode() + userMsgEntity.getToUserCode()));
            userMsgEntity.setRepliedFlag(0);
            // 用户发送消息条数存储
            if (!req.getContent().contains("destructTime")) { // 忽略私密照解锁记录
                userMsgDao.insert(userMsgEntity);
            }
        } else {

            userMsgEntity.setSessionId(SecureUtil.md5(userMsgEntity.getToUserCode() + userMsgEntity.getFromUserCode()));
            userMsgDao.insert(userMsgEntity);

        }
        return userMsgEntity;
    }


    private void storeMsgList(AddMessageReq req, String chatterUserCode, String sessionId) {
        UserMsgListEntity entity = new UserMsgListEntity();
        entity.setFromUserCode(req.getFromUserId());
        entity.setSource(req.getSource());
        entity.setToUserCode(req.getToUserId());
        entity.setMsgType(req.getObjectName());
        entity.setMsgId(req.getMsgUID());
        entity.setChatterUserCode(chatterUserCode);
        entity.setChatterCode(chatterUserCode);
        if (StringUtils.isBlank(chatterUserCode)) {
            entity.setSendTo(1);
            entity.setRepliedFlag(0);
            // 用户发送消息条数存储
            if (!req.getContent().contains("destructTime")) { // 忽略私密照解锁记录
                String chatterCode = storeUserMessageSendNum(req, chatterUserCode);
                entity.setChatterCode(chatterCode);
                userMsgListDao.insert(entity);

                // 插入未读消息数
                userMsgUnreadNumDao.saveUnReadMsgNum(req.getFromUserId(), req.getToUserId(), sessionId, chatterUserCode);


            }
        } else {
            entity.setSendTo(2);
            userMsgListDao.insert(entity);

            // 更新回复时间
            updateUserMsgRepliedGap(chatterUserCode, entity.getFromUserCode(), entity.getToUserCode(), entity.getGmtCreate());

            // 插入未读消息数
            userMsgUnreadNumDao.saveUnReadMsgNum(req.getFromUserId(), req.getToUserId(), sessionId, chatterUserCode);
            // 记录chatter发送消息总条数
            addChatterSendMsgNum(req.getFromUserId(), req.getToUserId(), chatterUserCode);

        }
    }

    /**
     * 记录chatter发送消息总条数
     */
    @Resource
    ChatterMsgSendTotalDao chatterMsgSendTotalDao;
    private void addChatterSendMsgNum(String fromUserId, String toUserId, String chatterUserCode) {
        final List<ChatterMsgSendTotalEntity> chatterSendRecords = chatterMsgSendTotalDao.listChatterMsgs(fromUserId, toUserId);
        if (org.springframework.util.CollectionUtils.isEmpty(chatterSendRecords)) {
            ChatterMsgSendTotalEntity newRecord = new ChatterMsgSendTotalEntity();
            newRecord.setFromUserCode(fromUserId);
            newRecord.setToUserCode(toUserId);
            newRecord.setChatterUserCode(chatterUserCode);
            newRecord.setMsgNum(1);
            chatterMsgSendTotalDao.insert(newRecord);

        } else {
            final ChatterMsgSendTotalEntity existsRecords = chatterSendRecords.get(0);
            existsRecords.setMsgNum(existsRecords.getMsgNum() + 1);
            chatterMsgSendTotalDao.updateByPrimaryKey(existsRecords);
        }

    }

    private void updateReplyTimes(String chatterUserCode, UserMsgEntity userMsgEntity) {
        updateUserMsgRepliedGap(chatterUserCode, userMsgEntity.getFromUserCode(), userMsgEntity.getToUserCode(), new Date());
    }


    private ChatterOptLogEntity addChatterOptLog(String chatterUserCode) {
        ChatterOptLogEntity entity = new ChatterOptLogEntity();
        entity.setUrl("chatterSendMessage");
        entity.setUserCode(chatterUserCode);
        chatterOptLogDao.insert(entity);
        return entity;
    }

    /**
     * 用户发送消息条数存储
     */
    private String storeUserMessageSendNum(AddMessageReq req, String chatterUserCode) {
        try {
            chatterUserCode = userMsgService.storeMsg(chatterUserCode, req.getFromUserId(), req.getToUserId());
        } catch (Exception e) {
            logger.error("userMsgService.storeMsg error, req:{}", JSONObject.toJSONString(req), e);
        }
        try {
            userMsgService.storeMsgForChatter(chatterUserCode, req.getFromUserId(), req.getToUserId());
        } catch (Exception e) {
            logger.error("userMsgService.storeMsgForChatter error, req:{}", JSONObject.toJSONString(req), e);
        }

        return chatterUserCode;
    }

    /**
     * 更新回复时间
     */
    @Resource
    UserMsgSendPreDayDao userMsgSendPreDayDao;
    private void updateUserMsgRepliedGap(String chatterUserCode, String modelUserCode, String userCode, Date currentDate) {

        try {
            try {
                userMsgDao.updateReplyTimesIfChatterReplied(userCode, modelUserCode);
                userMsgListDao.updateReplyTimesIfChatterReplied(userCode, modelUserCode);
                userMsgSendPreDayDao.updateReplied(userCode, modelUserCode);
            } catch (Exception e) {
                logger.error("=====updateUserMsgRepliedGap, userCode:{}, modelUserCode:{}", userCode, modelUserCode, e);
            }

            // 更新chatter回复时间
            try {
                final MessageCmStausEntity messageCmStatus = messageCmStausDao.getMessageCmStatus(userCode, modelUserCode);
                if (Objects.nonNull(messageCmStatus) && messageCmStatus.getAckTime() == null) {
                    messageCmStatus.setAckTime(new Date());
                    messageCmStausDao.updateByPrimaryKey(messageCmStatus);
                }
            } catch (Exception e) {
                logger.error("=====updateMessageCmStausEntityError, userCode:{}, modelUserCode:{}", userCode, modelUserCode, e);
            }

        } catch (Exception e) {
            logger.error("updateUserMsgRepliedGapError, chatterUserCode:{}, modelUserCode:{}, userCode:{}", chatterUserCode, modelUserCode, userCode, e);
        }
    }

    @Override
    public Response<SysMessageDto> messageList(String userCode) {
        if (StringUtils.isBlank(userCode)) {
            return Response.ok();
        }

        // 消息未读数
        final Integer totalUnReadMessages = messageDao.queryTotalUnReadMessages(userCode);
//        if (totalUnReadMessages == 0) {
//            return Response.ok();
//        }

        final List<TMessageEntity> messages = messageDao.queryAllMessages(userCode);
        if (CollectionUtils.isEmpty(messages)) {
            return Response.ok();
        }

        final List<MessageDto> messageDtos = messages.stream().map(o -> MessageDto.builder().msgCode(o.getMsgCode()).icon(o.getIcon()).title(o.getTitle()).msgType(o.getMsgType())
                .content(o.getMsg()).sendTime(getDate(o.getGmtCreate())).build()).collect(Collectors.toList());

        // 获取最近一条消息
        final TMessageEntity latestMessage = messages.get(0);
        String latestSendTime = null;
        if (Objects.nonNull(latestMessage)) {
            latestSendTime = getDate(latestMessage.getGmtCreate());
        }
        return Response.ok(SysMessageDto.builder().sendTime(latestSendTime).unreadNum(totalUnReadMessages).messages(messageDtos).build());
    }

    @Override
    public Response readMessage(ReadMessageReq readMessageDto) {
        if (Objects.isNull(readMessageDto) || CollectionUtils.isEmpty(readMessageDto.getReadMessages())) {
            return Response.ok();
        }
        final List<ReadMessageDto> readMessages = readMessageDto.getReadMessages();
        for (ReadMessageDto o : readMessages) {
            TMessageReadEntity entity = messageReadDao.queryUnReadMessages(o.getUserCode(), o.getMsgCode());
            if (Objects.isNull(entity)) {
                entity = new TMessageReadEntity();
                entity.setMsgCode(o.getMsgCode());
                entity.setUserCode(o.getUserCode());
                entity.setReadFlag(1);
                messageReadDao.insert(entity);
            } else {
                entity.setReadFlag(1);
                messageReadDao.updateByPrimaryKey(entity);
            }
        }

        return Response.ok();
    }


    public String getDate(Date date) {
        //6  February 2023 9:35
        String format = "d MMM, yyyy HH:mm:ss";
        SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.ENGLISH);
        return dateFormat.format(date);

    }


    private List<UserConversationEntity> getUserConversationEntities(AddMessageReq req) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("userCode", req.getFromUserId());
        params.put("targetId", req.getToUserId());
        return conversationDao.queryConversationByTargetIdAndUserCode(params);
    }

    @Override
    public Response storeCommonLog(CommonLogReq commonLogReq) {

        if (Objects.isNull(commonLogReq)) {
            return Response.ok();
        }
        logger.info("==storeCommonLog begin, commonLogReq:{}", JSONObject.toJSONString(commonLogReq));
        try {
            UserCommonLogEntity userCommonLogEntity = new UserCommonLogEntity();

            userCommonLogEntity.setEventName(commonLogReq.getEventName());
            userCommonLogEntity.setUserCode(commonLogReq.getUserCode());
            userCommonLogEntity.setCode(commonLogReq.getCode());
            userCommonLogEntity.setContent(commonLogReq.getContent());
            userCommonLogEntity.setAppVersionName(commonLogReq.getAppVersionName());
            userCommonLogEntity.setAppVersion(commonLogReq.getAppVersion());
            userCommonLogEntity.setAppflyersId(commonLogReq.getAppsFlyerUid());
            final UserCommonLogEntity result = commonLogDao.insert(userCommonLogEntity);

            logger.info("==storeCommonLog end, commonLogReq:{}", JSONObject.toJSONString(result));
            return Response.ok(result);
        } catch (Exception e) {
            logger.info("==errorStoreCommonLog, commonLogReq:{}", JSONObject.toJSONString(commonLogReq));
        }
        return Response.ok();
    }

    /**
     * 发送通知
     * type: 0-发送通知到userCode， 1-发送通知到userCode的会话列表中的用户
     */
    @Resource
    UserConversationDao userConversationDao;
    @Resource
    AsyncEventBus pushEventBus;

    @Override
    public Response pushNotification(String userCode, Integer type) {
        if (PushNotificationType.PUSH_TO_CHAT_LIST.getType() == type) {
            final UserEntity userEntity = userDao.selectByUserCode(userCode);

            if (Objects.isNull(userEntity)) {
                return Response.ok();
            }

            // 修改头像或昵称的为M或CM，需要通知meboo用户对会话数据进行刷新
            if (UserType.MODEL.getType() == userEntity.getUserType() || UserType.CHATTER_MODEL.getType() == userEntity.getUserType()) {
                final List<UserConversationEntity> userConversationEntities = getUserConversationEntities(userCode);
                if (CollectionUtils.isEmpty(userConversationEntities)) {
                    return Response.ok();
                }
                userConversationEntities.parallelStream().forEach(o -> {
                    // 头像修改成功通知客户端进行更新
                    pushEventBus.post(buildEvent(userCode, o.getUserCodeFriend(), AppEnum.MEBOO));
                });
            }
        }
        return Response.ok();
    }

    @Override
    public Response<Boolean> sendImageStatus(String modelUserCode,  String userCode, String imageCode) {
        boolean result = false;
        Integer sendImageCount = userImageVideoSendLogsDao.sendImageCount(modelUserCode,userCode, imageCode);
        if (sendImageCount >0) {
            result = true;
        }
        return Response.ok(result);
    }

    private List<UserConversationEntity> getUserConversationEntities(String userCode) {
        final HashMap<String, Object> params = Maps.newHashMap();
        params.put("userCode", userCode);
        params.put("deleted", 0);
        return userConversationDao.selectByParams(params);
    }

    private Event buildEvent(String fromUserCode, String toUserCode, AppEnum appEnum) {
        Map<String, Integer> params = Maps.newHashMap();
        params.put("type", ParameterTypeEnum.AVATAR_CHANGE.getId());
        return Event.builder().eventActionEnum(ActionEnum.PUSH_MSG).fromUserCode(fromUserCode).toUserCode(toUserCode).app(appEnum).content(JSONObject.toJSONString(params)).build();
    }

    @Override
    public String getFullImageUrl(String imageUrl) {
        return ImagePrefixUtils.getFullImageUrl(imageUrl);
    }

    @Override
    public String removePrefix(String imageUrl) {
        return ImagePrefixUtils.removePrefix(imageUrl);
    }


    /**
     * 获取注册页面配置信息
     */
    @Override
    public Response<List<RegisterConfigDto>> getRegisterConfigs(String appCode) {
        final List<PageContentConfigEntity> pageConfigs = pageContentConfigDao.listRegisterConfigs(PageType.getAllTypes(), appCode);
        if (CollectionUtils.isEmpty(pageConfigs)) {
            return Response.ok();
        }

        final Map<String, List<SystemDictEntity>> dictMaps = getSystemDictEntities();

        String name = userNameDictDao.getRandomName();

        final List<RegisterConfigDto> registerDts = pageConfigs.stream().map(o -> toDto(o, dictMaps, name)).collect(Collectors.toList());

        return Response.ok(registerDts);
    }

    @Override
    public Response<List<SystemQaDto>> getSystemQaList(String appCode) {
        List<SystemQaEntity> systemQaEntityList = systemQaDao.getSystemQaList(appCode);
        List<SystemQaDto> systemQaDtoList = new ArrayList<>();
        if (!systemQaEntityList.isEmpty()) {
            systemQaDtoList = systemQaEntityList.stream().map(o -> {
                SystemQaDto systemQaDto = new SystemQaDto();
                systemQaDto.setTitle(o.getTitle());
                systemQaDto.setContent(o.getContent());
                return systemQaDto;
            }).collect(Collectors.toList());
        }
        return Response.ok(systemQaDtoList);
    }

    /**
     * 同一组code归属到同一key下
     */
    @Nullable
    private Map<String, List<SystemDictEntity>> getSystemDictEntities() {
        List<String> codes = Lists.newArrayList();
        codes.add(ConstantType.I_WANT);
        codes.add(ConstantType.YOU_ACCEPT);
        codes.add(ConstantType.BODY_SHAPE);
        final List<SystemDictEntity> dictList = systemDictDao.listByCode(codes);
        if (CollectionUtils.isNotEmpty(dictList)) {
            return dictList.parallelStream().collect(Collectors.groupingBy(SystemDictEntity::getDictCode));
        }
        return null;
    }

    public static RegisterConfigDto toDto(PageContentConfigEntity entity, Map<String, List<SystemDictEntity>> dictMap, String name) {
        if (entity == null) {
            return null;
        }
        RegisterConfigDto dto = new RegisterConfigDto();
        BeanUtils.copyProperties(entity, dto);

        if (PageType.FILL_I_WANT.getType() == entity.getPageType()) {
            if (dictMap != null && dictMap.containsKey(ConstantType.I_WANT)) {
                final List<SystemDictEntity> iWantList = dictMap.get(ConstantType.I_WANT);
                if (CollectionUtils.isNotEmpty(iWantList)) {
                    final List<SelectVal> iWantDtoList = iWantList.stream().sorted(Comparator.comparing(SystemDictEntity::getOrderNum)).map(o -> SelectVal.builder().code(o.getId()).value(o.getDictName()).build()).collect(Collectors.toList());
                    dto.setIWantList(iWantDtoList);
                }
            }
            if (dictMap != null && dictMap.containsKey(ConstantType.YOU_ACCEPT)) {
                final List<SystemDictEntity> youAcceptList = dictMap.get(ConstantType.YOU_ACCEPT);
                if (CollectionUtils.isNotEmpty(youAcceptList)) {
                    final List<SelectVal> manAcceptDtoList = youAcceptList.stream().filter(o -> o.getExtendInfo() != null && "MAN".equals(o.getExtendInfo())).sorted(Comparator.comparing(SystemDictEntity::getOrderNum)).map(o -> SelectVal.builder().code(o.getId()).value(o.getDictName()).build()).collect(Collectors.toList());
                    dto.setYouAcceptForMan(manAcceptDtoList);
                    final List<SelectVal> womanAcceptList = youAcceptList.stream().filter(o -> o.getExtendInfo() != null && "WOMAN".equals(o.getExtendInfo())).sorted(Comparator.comparing(SystemDictEntity::getOrderNum)).map(o -> SelectVal.builder().code(o.getId()).value(o.getDictName()).build()).collect(Collectors.toList());
                    dto.setYouAcceptForWomen(womanAcceptList);
                }
            }
        }

        if (PageType.FILL_GENDER.getType() == entity.getPageType()) {
            if (dictMap != null && dictMap.containsKey(ConstantType.BODY_SHAPE)) {
                final List<SystemDictEntity> bodyShapeList = dictMap.get(ConstantType.BODY_SHAPE);
                if (CollectionUtils.isNotEmpty(bodyShapeList)) {
                    final List<SelectVal> manBodyShapeList = bodyShapeList.stream().filter(o -> o.getExtendInfo() != null && "MAN".equals(o.getExtendInfo())).sorted(Comparator.comparing(SystemDictEntity::getOrderNum)).map(o -> SelectVal.builder().code(o.getId()).value(o.getDictName()).iconUrl(o.getPhotoUrl()).build()).collect(Collectors.toList());
                    dto.setBodyShapeForMan(manBodyShapeList);
                    final List<SelectVal> womanBodyShapeList = bodyShapeList.stream().filter(o -> o.getExtendInfo() != null && "WOMAN".equals(o.getExtendInfo())).sorted(Comparator.comparing(SystemDictEntity::getOrderNum)).map(o -> SelectVal.builder().code(o.getId()).value(o.getDictName()).iconUrl(o.getPhotoUrl()).build()).collect(Collectors.toList());
                    dto.setBodyShapeForWoman(womanBodyShapeList);
                    dto.setBodyShapeForQueer(null);
                }
            }
        }

        if (PageType.FILL_PHOTO.getType() == entity.getPageType()) {
            dto.setAvatar(entity.getExtendInfo());
        }

        if (PageType.FILL_NICKNAME.getType() == entity.getPageType()) {
            if (StringUtils.isNotBlank(name)) {
                dto.setNickName(name);
            }
        }

        if (StringUtils.isEmpty(dto.getSecondTitle())) {
            dto.setSecondTitle(null);
        }

        return  dto;
    }


}
